#include "hough.h"

#include "conversion_grayscale.h"
#include "edge_laplacian.h"

Hough::Hough(PNM* img) :
    Transformation(img)
{
}

Hough::Hough(PNM* img, ImageViewer* super) :
    Transformation(img, super)
{
}

PNM* Hough::transform()
{   
    int thetaDensity = getParameter("theta_density").toInt();

	auto gray = new ConversionGrayscale(image);
	image = gray->transform();
	delete gray;
	

	if(getParameter("skip_edge_detection").toBool() == false)
	{
		auto edge = new EdgeLaplacian(image);
		edge->setSize(3);
		image = edge->transform();
		delete edge;
	}

	int rhoMax = (int)sqrt(pow(image->width(), 2) + pow(image->height(), 2));
	auto thetaSize = thetaDensity * 180;

	auto newImage = new PNM(thetaSize, rhoMax * 2 + 1, QImage::Format_Indexed8);

	auto hough = math::matrix<int>(newImage->width(), newImage->height());

	for (int i = 0; i < newImage->width(); i++)
		for (int j = 0; j < newImage->height(); j++)
			hough(i, j) = 0;

	float max = 0.0f;
	for (int i = 0; i < image->width(); i++)
	{
		for (int j = 0; j < image->height(); j++)
		{
			auto v = image->pixel(i, j);
			if(v > 0)
			{
				for (int k = 0; k < thetaSize; k++)
				{
					auto theta = (k * M_PI)/(180.0*thetaDensity);
					auto rho = round(i*cos(theta) + j*sin(theta));
					hough(k, rho+rhoMax)++;

					if(hough(k, rho+rhoMax) > max) max = hough(k, rho+rhoMax);
				}
			}
		}
	}

	for (int i = 0; i < newImage->width(); i++)
		for (int j = 0; j < newImage->height(); j++)
			newImage->setPixel(i, j, round(255*hough(i,j)/max));

	return newImage;
}
